/**
 * @file ZSuffixTreeWrapper.h
 * @brief wrapper for suffix tree
 * @detail
    defines several common suffix tree:
    (1) based on ascii: in another words, one 8-bit character is a unit
        class name: ZSuffixTreeASCII
        example:
       ----------------------------------------------------------------------
       |#include "ZSuffixTreeWrapper.h"
       |int main()
       |{
       |    ZSuffixTreeASCII st("aabbaabbbo", 10);
       |    st.Construct();
       |    return 0;
       |}
       ----------------------------------------------------------------------
    (2) based on UTF8: in another words, one utf8 character is a unit
        class name: ZSuffixTreeUTF8
        example:
       ----------------------------------------------------------------------
       |#include "ZSuffixTreeWrapper.h"
       |int main()
       |{
       |    ZSuffixTreeUTF8 st("", );
       |    st.Construct();
       |    return 0;
       |}
       ----------------------------------------------------------------------
    (3) based on stl string: in another words, one string is a unit
        class name: ZSuffixTreeUTF8
        example:
       ----------------------------------------------------------------------
       |#include "ZSuffixTreeWrapper.h"
       |int main()
       |{
       |    vector<string> v;
       |    v.push_back("Jack");
       |    v.push_back("Jeo");
       |    v.push_back("Jack");
       |    v.push_back("Jeo");
       |    v.push_back("Jolin");
       |    ZSuffixTreeString st;
       |    st.PushBack(&v[0], 1);
       |    st.PushBack(&v[1], 1);
       |    st.PushBack(&v[2], 1);
       |    st.PushBack(&v[3], 1);
       |    st.PushBack(&v[4], 1);
       |    return 0;
       |}
       ----------------------------------------------------------------------
 * @author babear.wangz
 * @date 2011-04-12
 */

#ifndef ZSuffixTreeWrapper_H
#define ZSuffixTreeWrapper_H

#include "ZSuffixTree.h"

#define SpaceParam ZSTBufferSpaceParameter
#define Sequence ZSTSequenceBuffer<char, ZTypeTraits<char>, SpaceParam>
#define HashMethod SequenceHash<char>

uint32_t WordLengthFuncAscii(Sequence*, size_t)
{
    return 1;
}

typedef ZSuffixTree<char, SpaceParam, Sequence,
    WordLengthFuncAscii, HashMethod> ZSuffixTreeASCII;

uint32_t WordLengthFuncUTF8(Sequence* seq, size_t idx)
{
    char c = (*seq)[idx];
    if ((c & 0x80) == 0x0) {
        return 1;
    } else if ((c & 0xE0) == 0xC0) {
        return 2;
    } else if ((c & 0xF0) == 0xE0) {
        return 3;
    } else if ((c & 0xF8) == 0xF0) {
        return 4;
    } else {
        return 1;
    }
}

typedef ZSuffixTree<char, SpaceParam, Sequence,
    WordLengthFuncUTF8, HashMethod> ZSuffixTreeUTF8;

#include <string>
#include <vector>
class StringSequence {
public:
    StringSequence(uint32_t cap = 0) {}
    StringSequence(const std::string* buf, uint32_t l)
    {
        for (uint32_t i = 0; i < l; ++i) {
            seq.push_back(buf[i]);
        }
    }
    ~StringSequence() {}
    bool PushBack(const std::string& elem)
    {
        seq.push_back(elem);
    }
    std::string& operator [] (size_t i)
    {
        return seq[i];
    }
    const std::string& operator [] (size_t i) const
    {
        return seq[i];
    }
    bool Equal(uint32_t s1, uint32_t s2, uint32_t l) const
    {
        for (uint32_t i = 0; i < l; ++i) {
            if (seq[s1+i] != seq[s2+i]) return false;
        }
        return true;
    }
    void Swap(StringSequence& seqbuf)
    {
        seq.swap(seqbuf.seq);
    }
    inline uint32_t Size() { return seq.size(); }
private:
    std::vector<std::string> seq;
};
uint32_t WordLengthFuncString(StringSequence*, size_t)
{
    return 1;
}
struct StringSequenceHash {
    static unsigned Hash(std::string* seq, uint32_t len)
    {
        ASSERT(len == 1);
        return SuperStringHash(seq->c_str(), seq->length());
    }
};
typedef ZSuffixTree<std::string, SpaceParam, StringSequence,
    WordLengthFuncString, StringSequenceHash> ZSuffixTreeString;

#undef HashMethod
#undef Sequence
#undef SpaceParam

#endif

